/*
 * Copyright (C) 2008 Universidade Federal de Campina Grande
 *  
 * This file is part of OurGrid. 
 *
 * OurGrid is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free 
 * Software Foundation, either version 3 of the License, or (at your option) 
 * any later version. 
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package org.ourgrid.acceptance.worker;

import org.junit.Before;
import org.junit.Test;
import org.ourgrid.acceptance.util.worker.Req_004_Util;
import org.ourgrid.acceptance.util.worker.Req_087_Util;
import org.ourgrid.acceptance.util.worker.Req_088_Util;
import org.ourgrid.acceptance.util.worker.Req_090_Util;
import org.ourgrid.acceptance.util.worker.Req_093_Util;
import org.ourgrid.common.interfaces.management.WorkerManagementClient;
import org.ourgrid.common.interfaces.to.WorkerStatus;
import org.ourgrid.reqtrace.ReqTest;
import org.ourgrid.worker.WorkerComponent;

import br.edu.ufcg.lsd.commune.identification.ContainerID;
import br.edu.ufcg.lsd.commune.identification.DeploymentID;
import br.edu.ufcg.lsd.commune.test.AcceptanceTestUtil;

@ReqTest(reqs="REQ090")
public class Req_090_Test extends WorkerAcceptanceTestCase {
	
	private DeploymentID peerID;
	private Req_004_Util req_004_Util = new Req_004_Util(getComponentContext());
	private Req_090_Util req_090_Util = new Req_090_Util(getComponentContext());
	private Req_093_Util req_093_Util = new Req_093_Util(getComponentContext());
	private Req_087_Util req_087_Util = new Req_087_Util(getComponentContext());
	private Req_088_Util req_088_Util = new Req_088_Util(getComponentContext());
	
	@Before
	public void setUp() throws Exception {
		super.setUp();
		String peerPubKey = workerAcceptanceUtil.simulateAuthentication();
		
		peerID = new DeploymentID(new ContainerID("username", "server", "module", peerPubKey), "peer");
	}

	/** 
	 * This tests contains the following steps:
	 * 
	 *    1. Start a Worker with the master peer public key property: "publicKey1";
	 *    2. A peer with the public key "publicKey222" sends a setPeer message to the Worker;
	 *           * Verify if the following warn message was logged: "The unknown peer [peerID] tried to set itself as manager of this Worker. This message was ignored. Unknown peer public key: [unknownPublicKey]."
	 *    3. Verify if the master peer is null
	 * 
	 */
	@ReqTest(test="AT-090.1", reqs="REQ090")
	@Test public void test_at_090_1_UnknownPeerDefinesItselfAsMasterPeer() throws Exception {
		// Start Worker
		WorkerComponent component = req_004_Util.startWorker();
		
		// Set peer with the public key "publicKey222" - expect a warn to be logged
		DeploymentID unknownID = new DeploymentID(new ContainerID("username222", "server222", "module222", "publicKey222"),
				"peer222");
		
		req_090_Util.setUnknownPeer(component, unknownID);
		
		// Verify if the master peer is null
		req_093_Util.getMasterPeer(null);
	}
	
	/**
	 * This tests contains the following steps:
	 * 
	 *    1. Start a Worker with the idleness detector DISABLED and the master peer public key property: "publicKey1";
	 *    2. A peer with the public key "publicKey1" sends a setPeer message to the Worker;
	 *           * Verify if the following info message was logged: The peer [peerID] set itself as manager of this Worker.
	 *           * Expect the Worker to send a status changed message to the peer, with the IDLE status
	 *    3. Verify if the master peer is [peerID]
	 * 
	 */
	@ReqTest(test="AT-090.2", reqs="REQ090")
	@Test public void test_at_090_2_PeerDefinesItselfAsMasterPeerWithoutIdlenessDetector() throws Exception {
		// Start Worker
		WorkerComponent component = req_004_Util.startWorker();
		
		// The same peer sends a setPeer message to the worker - expect an info to be logged
		req_090_Util.setKnownPeer(component, peerID, WorkerStatus.IDLE);
		
		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);	
	}
	
	/**
	 * This tests contains the following steps:
	 * 
	 *    1. Start a Worker with the idleness detector ENABLED and the master peer public key property: "publicKey1";
	 *    2. A peer with the public key "publicKey1" sends a setPeer message to the Worker;
	 *           * Verify if the following info message was logged: The peer [peerID] set itself as manager of this Worker.
	 *           * Expect the Worker to send a status changed message to the peer, with the OWNER status
	 *    3. Verify if the master peer is [peerID]
	 * 
	 */
	@ReqTest(test="AT-090.3", reqs="REQ090")
	@Test public void test_at_090_3_PeerDefinesItselfAsMasterPeerWithIdlenessDetector() throws Exception {
		// Start Worker
		WorkerComponent component = req_004_Util.startWorker(true);
		
		// The same peer sends a setPeer message to the worker - expect an info to be logged
		req_090_Util.setKnownPeer(component, peerID, WorkerStatus.OWNER);
		
		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);	
	}
	
	/**
	 * This tests contains the following steps:
	 * 
	 *    1. Start a Worker with the idleness detector DISABLED and the master peer public key property: "publicKey1";
	 *    2. Pause the Worker;
	 *           * Verify if the following info message was logged: "Worker has been PAUSED."
	 *           * Verify if the following debug message was logged: "Status changed from IDLE to OWNER."
	 *           * Verify if the ControlClient received the operation succeed message
	 *    3. Verify if the master peer is null
	 *    4. A peer with the public key "publicKey1" sends a setPeer message to the Worker;
	 *           * Verify if the following info message was logged: The peer [peerID] set itself as manager of this Worker.
	 *           * Expect the Worker to send a status changed message to the peer, with the OWNER status
	 *    5. Verify if the master peer is [peerID]
	 * 
	 */
	@ReqTest(test="AT-090.4", reqs="REQ090")
	@Test public void test_at_090_4_PeerDefinesItselfAsMasterPeerOnPausedWorker() throws Exception {
		// Start Worker
		WorkerComponent component = req_004_Util.startWorker();
		
		// Pause the worker
		req_087_Util.pauseIdleWorker(component);
		
		// Verify if the master peer is null
		req_093_Util.getMasterPeer(null);
		
		// Set the same peer as the worker's master peer
		req_090_Util.setKnownPeer(component, peerID, WorkerStatus.OWNER);
		
		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);
	}
	
	/**
	 * This tests contains the following steps:
	 * 
	 *    1. Start a Worker with the idleness detector ENABLED and the master peer public key property: "publicKey1";
	 *    2. Resume the Worker;
	 *           * Verify if the following info message was logged: "Worker has been RESUMED."
	 *           * Verify if the following debug message was logged: "Status changed from OWNER to IDLE."
	 *    3. Verify if the master peer is null
	 *    4. A peer with the public key "publicKey1" sends a setPeer message to the Worker;
	 *           * Verify if the following info message was logged: The peer [peerID] set itself as manager of this Worker.
	 *           * Expect the Worker to send a status changed message to the peer, with the IDLE status
	 *    5. Verify if the master peer is [peerID]
 	 * 
	 */
	@ReqTest(test="AT-090.5", reqs="REQ090")
	@Test public void test_at_090_5_PeerDefinesItselfAsMasterPeerOnIdleWorker() throws Exception {
		// Start Worker
		WorkerComponent component = req_004_Util.startWorker(true);
		
		// Resume the worker
		req_088_Util.resumeOwnerWorker(component);
		
		// Verify if the master peer is null
		req_093_Util.getMasterPeer(null);

		// Set the same peer as the worker's master peer
		req_090_Util.setKnownPeer(component, peerID, WorkerStatus.IDLE);

		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);
	}
	
	/**
	 * This tests contains the following steps:
	 * 
	 *    1. Start a Worker with the idleness detector DISABLED and the master peer public key property: "publicKey1";
	 *    2. Pause the Worker;
	 *           * Verify if the following info message was logged: "Worker has been PAUSED."
	 *           * Verify if the following debug message was logged: "Status changed from IDLE to OWNER."
	 *           * Verify if the ControlClient received the operation succeed message
	 *    3. Resume the Worker;
	 *           * Verify if the following info message was logged: "Worker has been RESUMED."
	 *           * Verify if the following debug message was logged: "Status changed from OWNER to IDLE."
	 *    4. Verify if the master peer is null
	 *    5. A peer with the public key "publicKey1" sends a setPeer message to the Worker;
	 *           * Verify if the following info message was logged: The peer [peerID] set itself as manager of this Worker.
	 *           * Expect the Worker to send a status changed message to the peer, with the IDLE status
	 *    6. Verify if the master peer is [peerID]
	 * 
	 */
	@ReqTest(test="AT-090.6", reqs="REQ090")
	@Test public void test_at_090_6_PeerDefinesItselfAsMasterPeerOnResumedWorker() throws Exception {
		// Start Worker
		WorkerComponent component = req_004_Util.startWorker();
		
		// Pause the worker
		req_087_Util.pauseIdleWorker(component);
		
		// Resume the worker
		req_088_Util.resumeOwnerWorker(component);
		
		// Verify if the master peer is null
		req_093_Util.getMasterPeer(null);

		// Set the same peer as the worker's master peer
		req_090_Util.setKnownPeer(component, peerID, WorkerStatus.IDLE);

		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);
	}
	
	/**
	 * This tests contains the following steps:
	 * 
	 *    1. Start a Worker with the idleness detector DISABLED and the master peer public key property: "publicKey1";
	 *    2. A peer with the public key "publicKey1" sends a setPeer message to the Worker;
	 *           * Verify if the following info message was logged: The peer [peerID] set itself as manager of this Worker.
	 *           * Send a status changed message to the peer, with the IDLE status
	 *    3. Verify if the master peer is [peerID]
	 *    4. Pause the Worker;
	 *           * Verify if the following info message was logged: "Worker has been PAUSED."
	 *           * Verify if the following debug message was logged: "Status changed from IDLE to OWNER."
	 *           * Expect the Worker to send the peer a status changed message, with the OWNER status
	 *           * Verify if the ControlClient received the operation succeed message
	 *    5. Verify if the master peer is [peerID]
	 *    6. Resume the Worker;
	 *           * Verify if the following info message was logged: "Worker has been RESUMED."
	 *           * Verify if the following debug message was logged: "Status changed from OWNER to IDLE."
	 *           * Expect the Worker to send the peer a status changed message, with the IDLE status
	 *    7. Verify if the master peer is [peerID]
	 * 
	 */
	@ReqTest(test="AT-090.7", reqs="REQ090")
	@Test public void test_at_090_7_WorkerWithDefinedMasterPeerPausesAndResumes() throws Exception {
		// Start Worker
		WorkerComponent component = req_004_Util.startWorker();
		
		// Set the same peer as the worker's master peer
		WorkerManagementClient wmc = req_090_Util.setKnownPeer(component, peerID, WorkerStatus.IDLE);
		
		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);
		
		// Pause the worker
		req_087_Util.pauseIdleWorkerWithoutCleaning(component, wmc);
		
		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);
		
		// Resume the worker
		req_088_Util.resumeWorker(component, wmc);

		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);
	}

	/**
	 * This tests contains the following steps:
	 * 
	 *    1. Start a Worker with the idleness detector DISABLED and the master peer public key property: "publicKey1";
	 *    2. A peer with the public key "publicKey1" sends a setPeer message to the Worker;
	 *           * Verify if the following info message was logged: The peer [peerID1] set itself as manager of this Worker.
	 *           * Expect the Worker to send a status changed message to the peer, with the IDLE status
	 *    3. Verify if the master peer is [peerID1]
	 *    4. The same peer with the same public key and the same ID (peerID1) sends a setPeer message to the Worker - Expect the Worker to:
	 *           * Verify if the following warn message was logged: The peer [peerID1] set itself as manager of this Worker. This message was ignored. Because the master peer did not notify fail.
	 *    5. Verify if the master peer is [peerID1]
	 *    6. Pause the Worker - Expect the Worker to:
	 *           * Verify if the following info message was logged: "Worker has been PAUSED."
	 *           * Verify if the following debug message was logged: "Status changed from IDLE to OWNER."
	 *           * Expect the Worker to send the peer a status changed message, with the OWNER status
	 *           * Verify if the ControlClient received the operation succeed message
	 *    7. A peer with the same public key but from a different location (peerID2) sends a setPeer message to the Worker - Expect the Worker to:
	 *           * Verify if the following warn message was logged: The peer [peerID2] set itself as manager of this Worker. This message was ignored. Because the master peer did not notify fail.
	 *    8. Verify if the master peer is [peerID1]
	 *    9. Resume the Worker - Expect the Worker to:
	 *           * Verify if the following info message was logged: "Worker has been RESUMED."
	 *           * Verify if the following debug message was logged: "Status changed from OWNER to IDLE."
	 *           * Expect the Worker to send the updated peer (peerID1) a status changed message, with the IDLE status
	 *   10. A peer with the public key "publicKey222" sends a setPeer message to the Worker;
	 *           * Verify if the following debug message was logged: "The unknown peer [peerID] tried to set itself as manager of this Worker. This message was ignored. Unknown peer public key: [unknownPublicKey]."
	 *   11. Pause the Worker - Expect the Worker to:
	 *           * Verify if the following info message was logged: "Worker has been PAUSED."
	 *           * Verify if the following debug message was logged: "Status changed from IDLE to OWNER."
	 *           * Expect the Worker to send the updated peer (peerID1) a status changed message, with the OWNER status
	 *           * Verify if the ControlClient received the operation succeed message
	 * 
	 */
	@ReqTest(test="AT-090.8", reqs="REQ090")
	@Test public void test_at_090_8_WorkerWithDefinedMasterPeerPausesAndResumes() throws Exception {
		// Start Worker
		WorkerComponent component = req_004_Util.startWorker(false);
		
		// Set the same peer as the worker's master peer
		WorkerManagementClient wmc = req_090_Util.setKnownPeer(component, peerID, WorkerStatus.IDLE);
		
		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);
		
		// Set the same peer as the worker's master peer
		req_090_Util.setPeerByMasterPeerFromSameLocation(component, peerID, WorkerStatus.IDLE, wmc);
		
		AcceptanceTestUtil.publishTestObject(component, peerID, wmc, WorkerManagementClient.class);
		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(peerID);
		
		// Pause the worker
		req_087_Util.pauseIdleWorkerWithoutCleaning(component, wmc);
		
		// Set a new peer as the worker's master peer
		DeploymentID anotherPeerID = new DeploymentID(new ContainerID("username2", "server2", "module2", peerID.getPublicKey()), "peer2");
		
		wmc = req_090_Util.setPeerByMasterPeerFromDiffLocation(component, anotherPeerID, WorkerStatus.OWNER);
		
		// Verify if the master peer is [peerID]
		req_093_Util.getMasterPeer(anotherPeerID);
		
		// Resume the worker
		req_088_Util.resumeWorker(component, wmc);
		
		// Set peer with the public key "publicKey222" - expect a warn to be logged
		DeploymentID unknownID = new DeploymentID(new ContainerID("username222", "server222", "module222", "publicKey222"), "peer222");
		
		req_090_Util.setUnknownPeer(component, unknownID);
		
		// Pause the worker
		req_087_Util.pauseIdleWorkerWithoutCleaning(component, wmc);
	}
	
}